package com.yyt.guavademo.model;

/**
 * @author yeyangtao
 * @since 2022/7/21 15:09
 */

import com.google.common.base.MoreObjects;
import com.google.common.base.Ticker;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class GuavaTester {
    public static void main(String args[]) {
        loadMethod();
        callableMethod();
    }

    private static void callableMethod() {
        Cache<Object, Object> cache = CacheBuilder.newBuilder().build();
        try {
            Object value = cache.get("111", new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    return "666";
                }
            });
            System.out.println(value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void loadMethod() {
        LoadingCache<String, String> cache =
                CacheBuilder.newBuilder()
                        .maximumSize(100)
                        .expireAfterAccess(30, TimeUnit.MINUTES)
                        .build(new CacheLoader<String, String>() {
                            @Override
                            public String load(String id) {
                                return "取不到数据会调用";
                            }
                        });
        try {
            cache.put("111", "666");
            System.out.println(cache.get("111"));
            System.out.println(cache.get("100"));

        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 参数示例
     *
     * @throws ExecutionException
     */
    private static void paramDemo() throws ExecutionException {
        LoadingCache<Object, Object> userCache = CacheBuilder.newBuilder()
                // 基于容量回收。缓存的最大数量。超过就取MAXIMUM_CAPACITY = 1 << 30。依靠LRU队列recencyQueue来进行容量淘汰
                .maximumSize(1000)
                // 基于容量回收。但这是统计占用内存大小，maximumWeight与maximumSize不能同时使用。设置最大总权重
                .maximumWeight(1000)
                // 设置权重（可当成每个缓存占用的大小）
                .weigher((o, o2) -> 5)
                // 软弱引用（引用强度顺序：强软弱虚）
                // -- 弱引用key
                .weakKeys()
                // -- 弱引用value
                .weakValues()
                // -- 软引用value
                .softValues()
                // 过期失效回收
                // -- 没读写访问下，超过5秒会失效(非自动失效，需有任意getput方法才会扫描过期失效数据)
                .expireAfterAccess(5L, TimeUnit.SECONDS)
                // -- 没写访问下，超过5秒会失效(非自动失效，需有任意putget方法才会扫描过期失效数据)
                .expireAfterWrite(5L, TimeUnit.SECONDS)
                // 没写访问下，超过5秒会失效(非自动失效，需有任意putget方法才会扫描过期失效数据。但区别是会开一个异步线程进行刷新，刷新过程中访问返回旧数据)
                .refreshAfterWrite(5L, TimeUnit.SECONDS)
                // 移除监听事件
                .removalListener(removal -> {
                    // 可做一些删除后动作，比如上报删除数据用于统计
                    System.out.printf("触发删除动作，删除的key=%s%n", removal);
                })
                // 并行等级。决定segment数量的参数，concurrencyLevel与maxWeight共同决定
                .concurrencyLevel(16)
                // 开启缓存统计。比如命中次数、未命中次数等
                .recordStats()
                // 所有segment的初始总容量大小
                .initialCapacity(512)
                // 用于测试，可任意改变当前时间。参考：https://www.geek-share.com/detail/2689756248.html
                .ticker(new Ticker() {
                    @Override
                    public long read() {
                        return 0;
                    }
                })
                .build(new CacheLoader<Object, Object>() {
                    @Override
                    public Object load(Object name) {
                        // 在cache找不到就取数据
                        return String.format("重新load（%s）：%s", System.currentTimeMillis(), name);
                    }
                });
        // 简单使用
        userCache.put("a", "aaa");
        System.out.println(userCache.get("a"));
    }
}